// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace SL.IdentityModel.Claims
{
    /// <summary>
    /// This class contains a collection of Claim objects
    /// </summary>
    public class ClaimCollection : IList<Claim>, ICollection<Claim>, IEnumerable<Claim>, IEnumerable
    {
        private List<Claim> _claims;

        /// <summary>
        /// Creates an instance of a ClaimsCollection object
        /// </summary>
        public ClaimCollection()
        {
            _claims = new List<Claim>();
        }

        /// <summary>
        /// Allows indexing claims based on ClaimType name or Uri
        /// If there are more than one  matching claims, the first wll be returned.
        /// 
        /// </summary>
        /// <example>claimsCollection["Email"] can be used to retieve the Email claim type</example>
        /// <param name="key"></param>
        /// <returns></returns>
        public Claim this[string key]
        {
            get
            {
                string claimType = key;
                Claim claim = null;

                if ( null == claimType )
                {
                    claimType = key;
                }

                claim = ( from c in _claims
                          where c.ClaimType == claimType
                          select c ).FirstOrDefault<Claim>();

                return claim;
            }
        }

        #region ICollection

        public int Count
        {
            get { return this._claims.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public void Clear()
        {
            _claims.Clear();
        }

        public void Add( Claim item )
        {
            if ( null == item )
            {
                throw new ArgumentNullException( "item" );
            }
            _claims.Add( item );
        }

        public bool Contains( Claim item )
        {
            return _claims.Contains( item );
        }

        public void CopyTo( Claim[] array, int arrayIndex )
        {
            _claims.CopyTo( array, arrayIndex );
        }

        public bool Remove( Claim item )
        {
            if ( item == null )
            {
                throw new ArgumentNullException( "item" );
            }

            if ( !_claims.Remove( item ) )
            {
                throw new InvalidOperationException( "attempt was made to remove an item that was not in the collection" );
            }

            return true;
        }
        #endregion

        #region IEnumerable<Claim>

        public IEnumerator<Claim> GetEnumerator()
        {
            return _claims.GetEnumerator();
        }

        #endregion

        #region IEnumerable

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _claims.GetEnumerator();
        }

        #endregion

        #region IList

        public Claim this[int index]
        {
            get { return this._claims[index]; }
            set { this.Insert( index, value ); }
        }

        public void AddRange( IEnumerable<Claim> collection )
        {
            if ( null == collection )
            {
                throw new ArgumentNullException( "collection" );
            }

            foreach ( Claim claim in collection )
            {
                this.Add( claim );
            }
        }

        public int IndexOf( Claim item )
        {
            return _claims.IndexOf( item );
        }

        public void Insert( int index, Claim item )
        {
            if ( ( index < 0 ) || ( index >= _claims.Count ) )
            {
                throw new ArgumentOutOfRangeException( "index" );
            }

            if ( item == null )
            {
                throw new ArgumentNullException( "item" );
            }

            _claims.Insert( index, item );
        }

        public void RemoveAt( int index )
        {
            if ( ( index < 0 ) || ( index >= _claims.Count ) )
            {
                throw new ArgumentOutOfRangeException( "index is out of supported rant" );
            }

            Claim item = _claims[index];
            this.Remove( item );
        }
        #endregion
    }
}